Counters: Asynchronous and Synchronous
Learning Objectives
By the end of this lesson, you should be able to:
- describe what a digital counter stores and outputs;
- calculate counter modulus, bit width, and output frequency division;
- compare asynchronous ripple counters with synchronous counters;
- design small up, down, and modulo-N counters;
- recognize glitches, reset hazards, and timing limits;
- verify counter behavior in hardware or HDL simulation.
What Is a Counter?
A counter is a sequential circuit that steps through a defined state sequence on clock events.
For an n-bit binary counter:
number of states = 2^n
count range = 0 to 2^n - 1
Example: a 4-bit counter has 2^4 = 16 states, from 0000 to 1111.
Counters are used for:
- event counting;
- timers and delays;
- frequency division;
- address generation;
- state sequencing;
- baud-rate and sampling clocks.
Frequency Division
Each bit of a binary counter divides the input clock by a power of two.
| Counter bit | Toggle rate |
|---|---|
| Q0 | fclk / 2 |
| Q1 | fclk / 4 |
| Q2 | fclk / 8 |
| Q3 | fclk / 16 |
General formula:
f(Qk) = fclk / 2^(k + 1)
where Q0 is the least significant bit.
Asynchronous Ripple Counter
In an asynchronous, or ripple, counter, the first flip-flop is clocked by the external clock. Each following flip-flop is clocked by the previous stage.
The output changes ripple from one stage to the next.
title "Ripple counter delay sketch"
time start=0 end=80 unit=ns divisions=8
CLK: square label="CLK" low=0 high=1 duty=50 cycles=4 unit=logic color=#2563eb
Q0: square label="Q0 delay after CLK" low=0 high=1 duty=50 cycles=2 phase=10 unit=logic color=#16a34a
Q1: square label="Q1 delay after Q0" low=0 high=1 duty=50 cycles=1 phase=20 unit=logic color=#dc2626
marker EDGE at=20 label="edge"
marker RIPPLE at=26 label="ripple settles"
This waveform is illustrative. Actual ripple delay depends on flip-flop propagation delay and loading.
Ripple Counter Advantages
- simple to build from toggle flip-flops;
- low gate count;
- useful for low-speed frequency division.
Ripple Counter Limitations
- outputs do not change at the same time;
- decoded outputs can glitch during ripple transitions;
- maximum clock speed falls as more stages are added;
- poor fit for high-speed synchronous systems.
Approximate worst-case ripple delay:
t_settle = n * tpd_flipflop
where n is the number of stages.
Synchronous Counter
In a synchronous counter, all flip-flops share the same clock. Combinational logic calculates each next state.
Because all bits update on the same clock edge, synchronous counters are preferred for CPUs, FPGAs, CPLDs, and timing-critical digital systems.
For a 3-bit binary up counter using T flip-flop behavior:
| Bit | Toggle condition |
|---|---|
| Q0 | always toggles |
| Q1 | toggles when Q0 = 1 |
| Q2 | toggles when Q1 Q0 = 11 |
Using D flip-flops, you normally describe the counter as:
always @(posedge clk) begin
if (rst) begin
count <= 3'b000;
end else begin
count <= count + 3'b001;
end
end
The synthesis tool builds the required next-state logic.
Up, Down, and Up-Down Counters
An up counter increments:
000, 001, 010, 011, 100, ...
A down counter decrements:
111, 110, 101, 100, 011, ...
An up-down counter chooses direction with a control signal.
always @(posedge clk) begin
if (rst) begin
count <= 4'd0;
end else if (up) begin
count <= count + 4'd1;
end else begin
count <= count - 4'd1;
end
end
Unsigned counters wrap naturally after their maximum value.
Modulo-N Counters
A modulo-N counter has N states before repeating.
Examples:
| Counter | States | Notes |
|---|---|---|
| MOD-10 decade | 0 to 9 | BCD counting |
| MOD-12 | 0 to 11 | clock hours or sequence logic |
| MOD-60 | 0 to 59 | seconds or minutes |
Minimum bit width:
bits = ceiling(log2(N))
For MOD-10:
ceiling(log2(10)) = 4 bits
Four bits provide 16 possible states, so states 10 to 15 must be unused or corrected.
Safe MOD-10 HDL
always @(posedge clk) begin
if (rst) begin
count <= 4'd0;
end else if (count == 4'd9) begin
count <= 4'd0;
end else begin
count <= count + 4'd1;
end
end
This synchronous version avoids glitchy asynchronous reset decoding.
Decoding Counter States
Decoding a counter state means detecting a particular binary value.
Example: detect count 9 (1001):
terminal_count = Q3 Q2' Q1' Q0
Use decoded terminal-count signals carefully:
- register them when they drive important enables;
- avoid using a ripple counter decode as a clock;
- consider whether the decoded pulse is one full clock cycle or only a narrow combinational pulse.
Worked Example: Create a 1 kHz Tick From 1 MHz
Goal: generate a one-clock-wide tick every 1 ms from a 1 MHz clock.
Clock period:
Tclk = 1 / 1 MHz = 1 us
Needed counts:
1 ms / 1 us = 1000 counts
Use a MOD-1000 counter. Bit width:
ceiling(log2(1000)) = 10 bits
Verilog:
reg [9:0] count;
reg tick;
always @(posedge clk) begin
if (rst) begin
count <= 10'd0;
tick <= 1'b0;
end else if (count == 10'd999) begin
count <= 10'd0;
tick <= 1'b1;
end else begin
count <= count + 10'd1;
tick <= 1'b0;
end
end
Expected behavior: tick is high for one clock cycle every 1000 input clocks.
Johnson and Ring Counters
A ring counter circulates a single 1 through a shift register:
0001 -> 0010 -> 0100 -> 1000 -> 0001
A Johnson counter feeds the inverted last output back to the first input:
0000 -> 0001 -> 0011 -> 0111 -> 1111 -> 1110 -> 1100 -> 1000 -> 0000
Ring counters are simple one-hot sequencers. Johnson counters produce 2n states from n flip-flops and can simplify decoding.
Practical Hardware Notes
- Debounce mechanical clock inputs before counting them.
- Use a Schmitt-trigger input for slow or noisy external pulses.
- Do not build high-speed clock trees from ripple counter outputs.
- In FPGA designs, use clock-enable pulses instead of divided clocks unless the clocking resources are designed for division.
- Include reset or self-correction for counters with unused states.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Using ripple output as a clean bus | transient wrong decoded values | use synchronous counters |
| Asynchronous decode reset for MOD-N | narrow glitches or missed reset | use synchronous terminal-count logic |
| Wrong bit-width calculation | counter wraps too early | use ceiling(log2(N)) |
| Button connected as clock | multiple counts per press | debounce and synchronize |
| Divided FPGA clock used casually | timing and CDC problems | use clock enable or clock manager |
Verification Checklist
- Simulate reset, first count, terminal count, and wraparound.
- Confirm count sequence includes exactly the intended states.
- Check terminal-count pulse width.
- Check
fout = fclk / division_ratio. - Check timing report for synchronous implementations.
- On hardware, probe clock, reset, count bits, and terminal-count output together.
Summary
Counters are flip-flop based state machines that step through numeric or symbolic sequences. Ripple counters are simple but have staged delays and glitch risks. Synchronous counters update all bits on the same clock edge and are the normal choice for reliable digital design. Modulo-N counters need enough bits plus correct terminal-count logic.
Further Reading
- M. Morris Mano and Michael Ciletti, Digital Design
- Texas Instruments datasheets for 74HC393, 74HC161, 74HC163, and 74HC190
- FPGA vendor clocking and clock-enable design guides
- Stephen Brown and Zvonko Vranesic, Fundamentals of Digital Logic with Verilog Design